﻿/*
 * Ext Gantt 1.2
 * Copyright(c) 2009-2011 Mats Bryntse Consulting
 * mats@ext-scheduler.com
 * http://www.ext-scheduler.com/license.html
 *
 */

Ext.ns('Sch.gantt');
 
/**
 * @class Sch.gantt.Resize
 * @extends Ext.util.Observable
 * Internal class enabling resizing of tasks
 * @constructor
 * @param {Object} config The object containing the configuration of this model.
 */
Sch.gantt.Resize = function(gantt, config) {
    Ext.apply(this, config);
    
    this.scheduler = gantt;
        
    this.scheduler.on({
        render : this.onSchedulerRender, 
        destroy : this.cleanUp,
        scope : this
    });

    Sch.gantt.Resize.superclass.constructor.call(this);
};
 
Ext.extend(Sch.gantt.Resize, Ext.util.Observable, {
    
    /**
     * @cfg {Boolean} showDuration true to show the duration instead of the end date when resizing a task
     */
    showDuration : true,
    
    /**
      * @cfg useTooltip {Boolean} false to not show a tooltip while resizing
      */
    useTooltip : true,
    
    /**
     * An empty function by default, but provided so that you can perform custom validation on 
     * the item being resized.
     * @param {Ext.data.Record} taskRecord The task being resized
     * @param {Date} startDate
     * @param {Date} endDate
     * @param {Event} e The event object
     * @return {Boolean} isValid True if the creation event is valid, else false to cancel
     */
    validatorFn : Ext.emptyFn,
    
    /**
     * @cfg {Object} validatorFnScope
     * The scope for the validatorFn
     */
    validatorFnScope : null,
    
    // private
    onSchedulerRender : function() {
        var s = this.scheduler;

        s.mon(s.getView().mainBody, 'mousedown', this.onMouseDown, this, { delegate : '.x-resizable-handle' });
    },
    
    onMouseDown : function(e) {
        var s = this.scheduler,
            domEl = e.getTarget(s.eventSelector),
            rec = s.resolveTask(domEl);

        if (s.fireEvent('beforeresize', s, rec, e) === false) {
            return;
        }
        e.stopEvent();
        this.createResizable(Ext.get(domEl), rec, e);
        s.fireEvent('resizestart', s, rec);
    },


    // private
    createResizable : function (el, eventRecord, e) {
       
        var t = e.getTarget(),
            s = this.scheduler,
            v = s.getView(),
            cm = s.getColumnModel(),
            isStart = !!t.className.match('x-resizable-handle-west'),
            widthIncrement = v.getSnapPixelAmount(),
            startLeft = el.getLeft(),
            startRight = el.getRight(),
            currentWidth = el.getWidth(),
            resourceRegion = el.up('.x-grid3-row').getRegion();

        this.resizable = new Sch.LazyResizable(el, {
                startLeft : startLeft,
                startRight : startRight,
                eventRecord : eventRecord,
                handles: isStart ? 'w' : 'e',
                dynamic: true,
                handleCls : 'x-hidden',
                maxWidth : currentWidth + (isStart ? (startLeft - resourceRegion.left) : (resourceRegion.right - startRight)),
                minWidth: widthIncrement,
                widthIncrement : widthIncrement,
                listeners : {
                    partialresize : { fn : this[isStart ? 'partialWestResize' : 'partialEastResize'], scope : this },
                    resize        : { fn : this.afterResize, scope : this }
                }
            },
            isStart ? 'west' : 'east',
            e
        );
        
        if (this.useTooltip) {
            if(!this.tip) {
                this.tip = new Sch.gantt.Tooltip({
                    mode : this.showDuration ? 'duration' : 'startend'
                }, s);
            }
            var start = eventRecord.get('StartDate'),
                end = eventRecord.get('EndDate');
            this.tip.show(el);
            this.tip.update(start, end, true);
        }
    },
    
    // private
    partialEastResize : function (r, newWidth, oldWidth, e) {
        var s = this.scheduler,
            end = s.getDateFromX(r.startLeft + Math.min(newWidth, this.resizable.maxWidth), 'round');
        
        if (!end) {
            return;
        }

        var start = r.eventRecord.get('StartDate'),
            valid = this.validatorFn.call(this.validatorFnScope || this, r.eventRecord, start, end) !== false;
        
        r.end = end;
        
        s.fireEvent('partialresize', s, r.eventRecord, start, end, r.el, e);
        
        if (this.useTooltip) {
            this.tip.update(start, end, valid);
        }
    },
    
    partialWestResize : function (r, newWidth, oldWidth, e) {
        var s = this.scheduler,
            start = s.getDateFromX(r.startRight - newWidth, 'round');
        
        if (!start) {
            return;
        }

        var end = r.eventRecord.get('EndDate'),
            valid = this.validatorFn.call(this.validatorFnScope || this, r.eventRecord, start, end) !== false;
        
        r.start = start;
        
        s.fireEvent('partialresize', s, r.eventRecord, start, end, r.el, e);
        
        if (this.useTooltip) {
            this.tip.update(start, end, valid);
        }
    },
    
    // private
    afterResize : function (r, w, h, e) {
        if (this.useTooltip) {
            this.tip.hide();
        }
        var eventRecord = r.eventRecord,
            oldStart = eventRecord.get('StartDate'),
            oldEnd = eventRecord.get('EndDate'),
            start = r.start || oldStart,
            end = r.end || oldEnd,
            scheduler = this.scheduler;
        
        if (start && end && (end - start > 0) && // Input sanity check
            ((start - oldStart !== 0) || (end - oldEnd !== 0)) && // Make sure start OR end changed
            this.validatorFn.call(this.validatorFnScope || this, eventRecord, start, end, e) !== false) {
            
            eventRecord.beginEdit();
            eventRecord.set('StartDate', start);
            eventRecord.set('EndDate', end);
            eventRecord.endEdit();
        } else {
            scheduler.getView().refreshRow(eventRecord);
        }
        
        // Destroy resizable 
        r.destroy();
        
        scheduler.fireEvent('afterresize', scheduler, eventRecord);
    },

    cleanUp : function() {
        if (this.tip) {
            this.tip.destroy();
        }
    }
}); 
